package com.xiang.ad.index;

import com.alibaba.fastjson.JSON;
import com.xiang.ad.dump.DConstant;
import com.xiang.ad.dump.table.AdCreativeTable;
import com.xiang.ad.dump.table.AdCreativeUnitTable;
import com.xiang.ad.dump.table.AdPlanTable;
import com.xiang.ad.dump.table.AdUnitDistrictTable;
import com.xiang.ad.dump.table.AdUnitItTable;
import com.xiang.ad.dump.table.AdUnitKeywordTable;
import com.xiang.ad.dump.table.AdUnitTable;
import com.xiang.ad.handler.AdLevelDataHandler;
import com.xiang.ad.mysql.constant.OpType;
import org.springframework.context.annotation.DependsOn;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import java.io.BufferedReader;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.List;
import java.util.stream.Collectors;

/**
 * Created by xiang.
 * 实现读取保存的全量的数据文件去构造或者加载全量索引
 */
@Component
//由于IndexFileLoader会是用到AdLevelDataHandler，AdLevelDataHandler会使用到datatable，datatable也是一个组件
//IndexFileLoader会依赖于datatable
@DependsOn("dataTable")
public class IndexFileLoader {

    /**
     * 实现全量索引的加载
     * 在检索系统启动的时候 就应该完成全量索引的加载
     * 也就是说，当IndexFileLoader加载到spring容器中之后，init方法就应该被执行,所以使用@PostConstruct
     * 加载过程是根据层级去定义的，因为层级之间是存在依赖关系的，顺序不能乱，2-3-4
     */
    @PostConstruct
    public void init() {

        //第2层级-推广计划 全量索引的加载
        //调用loadDumpData 根据文件路径 读取 数据文件
        List<String> adPlanStrings = loadDumpData(
                //拼接在ad-common模块中定义的文件的路径
                String.format("%s%s",
                        DConstant.DATA_ROOT_DIR,
                        DConstant.AD_PLAN)
        );
        //遍历数据文件 加载全量索引---添加索引
        adPlanStrings.forEach(p -> AdLevelDataHandler.handleLevel2(
                //从数据库中读取的时候已经将数据转变成xxxtable(json)再去序列化成string保存在数据文件中
                JSON.parseObject(p, AdPlanTable.class),//将数据文件反序列化回来
                OpType.ADD
        ));

        //第2层级-创意 全量索引的加载---添加索引
        //调用loadDumpData 根据文件路径 读取  数据文件
        List<String> adCreativeStrings = loadDumpData(
                //拼接在ad-common模块中定义的文件的路径
                String.format("%s%s",
                        DConstant.DATA_ROOT_DIR,
                        DConstant.AD_CREATIVE)
        );
        adCreativeStrings.forEach(c -> AdLevelDataHandler.handleLevel2(
                JSON.parseObject(c, AdCreativeTable.class),
                OpType.ADD
        ));

        //第3层级-推广单元 全量索引的加载
        //调用loadDumpData 根据文件路径 读取  数据文件
        List<String> adUnitStrings = loadDumpData(
                //拼接在ad-common模块中定义的文件的路径
                String.format("%s%s",
                        DConstant.DATA_ROOT_DIR,
                        DConstant.AD_UNIT)
        );
        adUnitStrings.forEach(u -> AdLevelDataHandler.handleLevel3(
                JSON.parseObject(u, AdUnitTable.class),
                OpType.ADD
        ));

        //第3层级-创意&推广单元关联关系 全量索引的加载
        //调用loadDumpData 根据文件路径 读取  数据文件
        List<String> adCreativeUnitStrings = loadDumpData(
                //拼接在ad-common模块中定义的文件的路径
                String.format("%s%s",
                        DConstant.DATA_ROOT_DIR,
                        DConstant.AD_CREATIVE_UNIT)
        );
        adCreativeUnitStrings.forEach(cu -> AdLevelDataHandler.handleLevel3(
                JSON.parseObject(cu, AdCreativeUnitTable.class),
                OpType.ADD
        ));

        //第4层级-地域限制 全量索引的加载
        //调用loadDumpData 根据文件路径 读取  数据文件
        List<String> adUnitDistrictStrings = loadDumpData(
                //拼接在ad-common模块中定义的文件的路径
                String.format("%s%s",
                        DConstant.DATA_ROOT_DIR,
                        DConstant.AD_UNIT_DISTRICT)
        );
        adUnitDistrictStrings.forEach(d -> AdLevelDataHandler.handleLevel4(
                JSON.parseObject(d, AdUnitDistrictTable.class),
                OpType.ADD
        ));

        //第4层级-兴趣限制 全量索引的加载
        //调用loadDumpData 根据文件路径 读取  数据文件
        List<String> adUnitItStrings = loadDumpData(
                //拼接在ad-common模块中定义的文件的路径
                String.format("%s%s",
                        DConstant.DATA_ROOT_DIR,
                        DConstant.AD_UNIT_IT)
        );
        adUnitItStrings.forEach(i -> AdLevelDataHandler.handleLevel4(
                JSON.parseObject(i, AdUnitItTable.class),
                OpType.ADD
        ));

        //第4层级-关键词限制 全量索引的加载
        //调用loadDumpData 根据文件路径 读取  数据文件
        List<String> adUnitKeywordStrings = loadDumpData(
                //拼接在ad-common模块中定义的文件的路径
                String.format("%s%s",
                        DConstant.DATA_ROOT_DIR,
                        DConstant.AD_UNIT_KEYWORD)
        );
        adUnitKeywordStrings.forEach(k -> AdLevelDataHandler.handleLevel4(
                JSON.parseObject(k, AdUnitKeywordTable.class),
                OpType.ADD
        ));
    }

    //实现 读取数据文件 并把他转换成List<String> 一行一行的string
    private List<String> loadDumpData(String fileName) {
        //通过指定文件路径，读取数据文件到buffer中
        try (BufferedReader br = Files.newBufferedReader(
                Paths.get(fileName)
        )) {
            return br.lines().collect(Collectors.toList());//将数据文件转化成list<String>
        } catch (IOException ex) {
            throw new RuntimeException(ex.getMessage());
        }
    }
}
